<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * Rauth Library
 * 
 * Provides functions to ease authentication and user management stuff :)
 * 
 * @author Burak Gunusen <burakgunusen@gmail.com>
 * @package Re-Authenticate
 */
    
    /**
    * Authentication Helper Library    
    */
    class Rauth
    {
        var $ci;
        var $view_path;
                
        function Rauth()
        {
            $this->ci = &get_instance();
            if( !class_exists('CI_Session') )
                $this->ci->load->library('Session');            
            if( !class_exists('CI_Database') )
                $this->ci->load->database();
            if( !class_exists('Ram') )
                $this->ci->load->model('Ram');                   
                
            $this->ci->config->load('rauth_config',TRUE);            
            $this->ci->lang->load('rauth');
            $this->view_path = $this->ci->config->item('templates_path','rauth_config');
            log_message('debug','Rauth Initialized');            
        }      
        
        /**
        * Sends mail :)
        * 
        * @param string $to
        * @param string $subject
        * @param string $body
        */
        function _send_mail( $to, $subject, $body )
        {
            if( !class_exists('CI_Email') )
                $this->ci->load->library('email');
            
            $config['mailtype'] = 'html';
            $config['charset'] = 'utf-8';
            $config['wordwrap'] = FALSE;
            $config['useragent'] = 'Rauth';
            
            $this->ci->email->initialize($config); 
            
            $from_addr  = $this->ci->config->item('webmaster_address','rauth_config');
            $from_name  = $this->ci->config->item('webmaster_name','rauth_config');              
            $this->ci->email->from( $from_addr, $from_name);
            $this->ci->email->to( $to);
            $this->ci->email->subject( $subject );
            $this->ci->email->message( $body );
            log_message('debug','sending mail '.$subject.' to :'.$to);
            log_message('debug','mail body:'.$body);
            return $this->ci->email->send();                                           
        }
        /**
        * generates authentication token
        *        
        * @param integer $user_id
        * @param string $password
        * @return string token
        */
        function _generate_authentication_token( $user_id, $user_password)
        {
            return sha1($user_id.$user_password);
        }
        /**
        * generates a random word to be used as salt
        * 
        */
        function _generate_salt()
        {
            return substr( md5(microtime()),1,8 );
        }
        /**
        * Creates a hash of given password based on configuration 
        *         
        * @param mixed $password
        * @param mixed $salt
        * @return string
        */
        function do_hash( $password, $salt='' )
        {
            $hashed_password = $password;                                  
            log_message('debug','hash function is '.$this->ci->config->item('hash_function','rauth_config') );
            if( $this->ci->config->item('hash_function','rauth_config') == 'md5' )
                $hashed_password = md5( $password.$salt );
            else if( $this->ci->config->item('hash_function','rauth_config') == 'sha1' )
                $hashed_password = sha1( $password.$salt );                
           log_message('debug','password hash is '.$hashed_password );
            return $hashed_password;                
        }
        /**
        * Checks if user account is confirmed or not
        *                 
        * @param integer $user_id
        */
        function is_confirmed_user( $user_id )
        {
            $user_row = $this->ci->Ram->find_user_by_id( $user_id );
            return $user_row->confirmed == 1;
        }
        /**
        * Checks if user is banned or not
        * 
        * @param integer $user_id
        */
        function is_banned_user( $user_id )
        {
            $user_row = $this->ci->Ram->find_user_by_id( $user_id );
            return $user_row->banned == 1;
        }    
        /**
        * authenticates user based on cookie
        *         
        */
        function auto_authenticate()
        {                        
            if( $this->is_authenticated() )
                return;
                        
            if( !file_exists('get_cookie') )
                $this->ci->load->helper('cookie');            
            $cookie_data = base64_decode( get_cookie( $this->ci->config->item('cookie_name','rauth_config') ) );            
            $cookie_parts = explode(':',$cookie_data );
            $user_id = -1;
            if( count($cookie_parts) == 2 )
                list( $user_id , $token ) = $cookie_parts;
            $user_row = $this->ci->Ram->find_user_by_id( $user_id );
            if( isset($user_row) )
            {
                if( $token == $this->_generate_authentication_token( $user_row->id, $user_row->password ) )
                   $this->authenticate( $user_row->email,$user_row->password );    
            }
            
        }     
        /**
        * Tries to authenticate user
        * 
        * @param string $email
        * @param string $password
        */
        function authenticate( $email, $password,$remember_user = false )
        {
            $user_row = $this->ci->Ram->find_user_by_email( $email );      
            log_message('debug','checking user row');
            if( !isset($user_row) )
                return false;      
            log_message('debug','hashing for login');                
            $hashed_pass = $this->do_hash( $password, $user_row->password_salt );
            log_message('debug','checking login pass and keys');
            if( $user_row->password == $hashed_pass && !$this->is_banned_user($user_row->id) && $this->is_confirmed_user($user_row->id) )
            {
                $this->add_parameter('rauth_user_id',$user_row->id );                                
                $this->add_parameter('rauth_token',$this->_generate_authentication_token( $user_row->id,$user_row->password )); 
                $this->ci->Ram->complete_authentication( $user_row->id ); 
                if( $remember_user )
                {
                    if( !function_exists('set_cookie') )
                        $this->ci->load->helper('cookie');
                    $token = $this->_generate_authentication_token( $user_row->id, $user_row->password );
                    // TODO 2 -o Rauth Library -c Rauth :add domain parameter
                    set_cookie( array(  'name'=>$this->ci->config->item('cookie_name','rauth_config'),
                                        'value'=> base64_encode("{$user_row->id}:$token"),
                                        'expire'=>'105000' ) 
                                     );
                }
                return true;                              
            }
            return false;
        }
        function logout()
        {
            $this->remove_parameter('rauth_user_id');    
            $this->remove_parameter('rauth_token');  
            if( !file_exists('delete_cookie') )
                $this->ci->load->helper('cookie');
            delete_cookie( $this->ci->config->item('cookie_name','rauth_config') );
        }
        /**
        * checks if active session is authenticated
        * 
        */
        function is_authenticated()
        {
            $user_id    = $this->get_parameter('rauth_user_id');
            $token      = $this->get_parameter('rauth_token');
            if( !isset($user_id) || !isset($token) )
                return false;
            $user_row   = $this->ci->Ram->find_user_by_id( $user_id );
            return ( $this->_generate_authentication_token($user_row->id,$user_row->password) == $token );
        }
        /**
        * returns the logged in user row
        * on error returns null
        */
        function active_user()
        {
            $user_id    = $this->get_parameter('rauth_user_id');
            $token      = $this->get_parameter('rauth_token');
            $user_row   = $this->ci->Ram->find_user_by_id( $user_id );
            if ( sha1($user_row->id.$user_row->password) == $token ) 
                return $user_row;
            return null;                                
        }
        function send_new_password( $user_id, $password_hash )
        {
            $user_row = $this->ci->Ram->find_user_by_id( $user_id );
            if( $user_row->password_reset_hash != $password_hash )
            {
                return false;                
            }
            $password = $this->ci->Ram->reset_password( $user_row->id );            
            $subject = $this->ci->lang->line('new_password_email_subject');
            $template['web_site_name']  = $this->ci->lang->line('web_site_name');
            $template['password']       = $password;            
            $template['domain_name']    = $this->ci->config->item('domain_name','rauth_config');
            $body = $this->ci->load->view($this->view_path.'/rauth/email/new_password',$template,TRUE);
            return $this->_send_mail( $user_row->email,$subject, $body );            
        }
        
        /**
        * Sends user a mail describing password reset phase has been initiated
        * 
        * @param integer $user_id
        */
        
        function send_password_reset_request_mail( $email )
        {   
            $user_row = $this->ci->Ram->find_user_by_email( $email );                        

            $subject    = $this->ci->lang->line('password_reset_request_email_subject');            
            $confirm_hash = $this->ci->Ram->create_password_reset_hash( $user_row->id );
            $confirmation_url = $this->ci->config->site_url().$this->ci->config->item('request_reset_password_url','rauth_config');
            $confirmation_url = str_replace( array('[id]','[confirm_hash]'),
                                             array($user_row->id,$confirm_hash),   
                                             $confirmation_url
                                            );                                                         
            $template['confirmation_url']   = $confirmation_url;
            $template['web_site_name']      = $this->ci->lang->line('web_site_name');
            $body = $this->ci->load->view($this->view_path.'/rauth/email/password_reset_request',$template,TRUE);
            return $this->_send_mail( $user_row->email,$subject, $body );
        }
        /**
        * Sends user a confirmation mail message
        * 
        * @param integer $user_id
        * @param string $confirm_hash
        */
        function send_activation_mail( $user_id, $confirm_hash )
        {
            $user_row = $this->ci->Ram->find_user_by_id( $user_id );
                                    
            $subject    = $this->ci->lang->line('activation_email_subject');                        
            $confirmation_url = $this->ci->config->site_url().$this->ci->config->item('confirmation_url','rauth_config');
            $confirmation_url = str_replace( array('[id]','[confirm_hash]'),
                                             array($user_id,$confirm_hash),   
                                             $confirmation_url
                                            ); 
                                            
            $template['domain_name']        = $this->ci->config->item('domain_name','rauth_config');
            $template['confirmation_url']   = $confirmation_url;
            $template['web_site_name']      = $this->ci->lang->line('web_site_name');
            $body = $this->ci->load->view($this->view_path.'/rauth/email/activation_email',$template,TRUE);
            return $this->_send_mail( $user_row->email,$subject, $body );
        }
        
        ////////////////////////////////////////////////////////////////////////////////////
        
        /*
        *   Session helper functions        
        */
        /**
        * Adds a parameter to session 
        * 
        * @param string $param_name
        * @param mixed $param_value
        */
        function add_parameter( $param_name, $param_value )
        {
            $this->ci->session->set_userdata( array( $param_name => $param_value ) );
        }
        /**
        * Gets a registered parameter. If parameter is not found then returns null
        * 
        * @param string $param_name
        */
        function get_parameter( $param_name )
        {
            $param_value = $this->ci->session->userdata( $param_name);
            return (  $param_value == FALSE )?null:$param_value;
        }
        function remove_parameter( $param_name )
        {
            $this->ci->session->unset_userdata( $param_name );            
        }        
                       
    }
?>
